package level.editor.control.select;

import utility.ImageUtility;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.event.WindowEvent;
import java.awt.event.WindowFocusListener;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.SwingUtilities;

import level.editor.control.Handler;
import level.editor.control.main.Main;
import level.editor.control.main.MainTabbed;
import level.model.Addable;
import level.model.Selection;
import level.model.Tile;

public class SelectHandler extends Handler implements WindowFocusListener
{
	// BUG: Initial object should allow for keyboard events
	public SelectHandler(MainTabbed tabbed)
	{
		this.tabbed = tabbed;
		type = TYPE_SINGLE;
		addType = false;
		buffer = new SelectBuffer(SELECT_BUFFER, tabbed.getSelectedMain());
		start = 0;
	}

	@Override
	public void mouseClicked(MouseEvent e)
	{
		if (SwingUtilities.isLeftMouseButton(e))
		{
			if (!addType)
				buffer.finish();
			buffer.setInitGhost(null);
			buffer.setEndGhost(null);
			type = TYPE_SINGLE;
			Main main = tabbed.getSelectedMain();
			Selection selection = main.select(noSnapPoint(main.getOrigin(),
					e.getPoint()));
			if (selection != null && !selection.isEmpty())
			{
				buffer.add(selection);
			}
			buffer.repaint();
			main.repaint();
		}
	}

	@Override
	public void mousePressed(MouseEvent e)
	{
		if (SwingUtilities.isLeftMouseButton(e))
		{
			type = TYPE_SINGLE;
			Main main = tabbed.getSelectedMain();
			buffer.setInitGhost(noSnapPoint(main.getOrigin(), e.getPoint()));
			buffer.repaint();
			main.repaint();
		}
	}

	@Override
	public void mouseReleased(MouseEvent e)
	{
		if (SwingUtilities.isLeftMouseButton(e))
		{
			start = System.nanoTime();
			if (!addType)
			{
				buffer.finish();
				if (type == TYPE_RECTANGLE)
				{
					Main main = tabbed.getSelectedMain();
					Selection selection = main.select(buffer.getRectangle());
					if (selection != null && !selection.isEmpty())
					{
						buffer.add(selection);
					}
				}
			}
			
			buffer.setInitGhost(null);
			buffer.setEndGhost(null);
			
			// Add rectangle selection here

			buffer.repaint();
			tabbed.getSelectedMain().repaint();
			System.out.println("Time: " + (System.nanoTime() - start)/1000000000.0f);
		}
	}

	@Override
	public void mouseDragged(MouseEvent e)
	{
		if (SwingUtilities.isLeftMouseButton(e))
		{
			type = TYPE_RECTANGLE;
			Main main = tabbed.getSelectedMain();
			buffer.setEndGhost(noSnapPoint(main.getOrigin(), e.getPoint()));
			main.repaint();
		}
	}

	@Override
	public void paint(Graphics2D g, Point topLeft)
	{
		String selectString = "Selection:  ";
		if (buffer == null)
			selectString += "None";
		else
		{
			for (Integer i : buffer.getSelection().keySet())
			{
				for (Addable addable : buffer.getSelection().get(i))
				{
					if (addable instanceof Tile)
					{
						Tile tile = (Tile) addable;
						try
						{
							g.drawImage(
									ImageUtility.makeColorTransparent(
											ImageIO.read(new File(tile
													.getIconPath())),
											new Color(255, 0, 255)),
									(int) (topLeft.getX() + TOOL_X_OFFSET),
									(int) (topLeft.getY() + TOOL_Y_OFFSET),
									(int) (topLeft.getX() + TOOL_X_OFFSET + tile
											.getW()), (int) (topLeft.getY()
											+ TOOL_Y_OFFSET + tile.getH()),
									(int) tile.getSx(), (int) tile.getSy(),
									(int) tile.getSx() + tile.getSw(),
									(int) tile.getSy() + tile.getSh(), null);
						}
						catch (IOException e)
						{
							e.printStackTrace();
						}
					}
				}
			}
		}
		g.drawString(selectString, (int) topLeft.getX(), (int) topLeft.getY());

		String typeString = "Type:  ";

		typeString += type + (addType ? TYPE_ADD : "");
		g.drawString(typeString, (int) topLeft.getX(),
				(int) (topLeft.getY() + TYPE_Y_OFFSET));
	}

	@Override
	public void finish()
	{
		// TODO Auto-generated method stub

	}

	@Override
	public void keyPressed(KeyEvent e)
	{
		if (e.getKeyCode() == KeyEvent.VK_SHIFT)
		{
			addType = true;
			tabbed.getSelectedMain().repaint();
		}
		
		if (e.getKeyCode() == KeyEvent.VK_DELETE)
		{
			buffer.delete();
		}
	}

	@Override
	public void keyReleased(KeyEvent e)
	{
		if (e.getKeyCode() == KeyEvent.VK_SHIFT)
		{
			addType = false;
			tabbed.getSelectedMain().repaint();
		}
	}

	@Override
	public void windowGainedFocus(WindowEvent arg0)
	{
		// TODO Auto-generated method stub

	}

	@Override
	public void windowLostFocus(WindowEvent arg0)
	{
		type = TYPE_SINGLE;
		if (tabbed.getSelectedMain() != null)
			tabbed.getSelectedMain().repaint();
	}

	private Point noSnapPoint(Point origin, Point initialPoint)
	{
		Point point = new Point();

		point.x = (int) (initialPoint.getX() - origin.getX());
		point.y = (int) (initialPoint.getY() - origin.getY());

		return point;
	}

	private MainTabbed tabbed;
	private String type;
	private boolean addType;
	private SelectBuffer buffer;
	private static final int TOOL_X_OFFSET = 75;
	private static final int TOOL_Y_OFFSET = -20;
	private static final int TYPE_Y_OFFSET = 80;
	private static final int SELECT_BUFFER = 102;

	private static final String TYPE_ADD = " (Add)";
	private static final String TYPE_SINGLE = "Single";
	private static final String TYPE_RECTANGLE = "Drag Rectangle";
	private long start;
}
